#ifndef POWER_MONITOR_H
#define POWER_MONITOR_H

#include <Arduino.h>

// 电力数据结构
typedef struct {
  unsigned long timestamp; // 时间戳
  float voltage;           // 电压 (V)
  float current;           // 电流 (A)
  float power;             // 功率 (W)
  float energy;            // 电能 (kWh)
} PowerData;

class PowerMonitor {
private:
  int currentSensorPin;    // 电流传感器引脚
  int voltageSensorPin;    // 电压传感器引脚
  
  // 校准参数
  float currentCalibrationFactor; // 电流校准因子
  float voltageCalibrationFactor; // 电压校准因子
  
  // 累积电能计算
  unsigned long previousMillis;   // 上一次计算的时间
  float accumulatedEnergy;        // 累积电能 (kWh)
  
  // 低通滤波器参数
  static const int FILTER_SAMPLES = 10; // 滤波样本数
  float currentSamples[FILTER_SAMPLES]; // 电流采样缓冲区
  float voltageSamples[FILTER_SAMPLES]; // 电压采样缓冲区
  int sampleIndex;                  // 采样索引
  
  // 计算平均值（低通滤波）
  float calculateFilteredValue(float* samples, int size);
  
  // 读取原始电流值
  float readRawCurrent();
  
  // 读取原始电压值
  float readRawVoltage();
  
  // 计算功率
  float calculatePower(float voltage, float current);
  
  // 计算电能
  void calculateEnergy(float power);
  
public:
  // 构造函数
  PowerMonitor(int currentPin, int voltagePin);
  
  // 初始化电力监测器
  void init();
  
  // 读取电力数据
  PowerData readData();
  
  // 设置校准参数
  void setCalibrationFactors(float currentFactor, float voltageFactor);
  
  // 获取累积电能
  float getAccumulatedEnergy();
  
  // 重置累积电能
  void resetAccumulatedEnergy();
  
  // 自检功能
  bool selfTest();
  
  // 诊断功能
  void runDiagnostics();
}; // 类定义结束

// 构造函数
PowerMonitor::PowerMonitor(int currentPin, int voltagePin) {
  currentSensorPin = currentPin;
  voltageSensorPin = voltagePin;
  
  // 默认校准参数
  currentCalibrationFactor = 0.185; // 适用于ACS712 5A传感器
  voltageCalibrationFactor = 0.012; // 适用于分压电路（例如100kΩ和10kΩ电阻）
  
  // 初始化累积电能计算
  previousMillis = millis();
  accumulatedEnergy = 0.0;
  
  // 初始化滤波器缓冲区
  for (int i = 0; i < FILTER_SAMPLES; i++) {
    currentSamples[i] = 0.0;
    voltageSamples[i] = 0.0;
  }
  sampleIndex = 0;
}

// 初始化电力监测器
void PowerMonitor::init() {
  pinMode(currentSensorPin, INPUT);
  pinMode(voltageSensorPin, INPUT);
  Serial.println("电力监测器已初始化");
}

// 计算平均值（低通滤波）
float PowerMonitor::calculateFilteredValue(float* samples, int size) {
  float sum = 0.0;
  for (int i = 0; i < size; i++) {
    sum += samples[i];
  }
  return sum / size;
}

// 读取原始电流值
float PowerMonitor::readRawCurrent() {
  // 读取电流传感器的原始值
  int rawValue = analogRead(currentSensorPin);
  
  // 将原始值转换为电流值 (A)
  // 假设Arduino的参考电压为5V，ADC分辨率为10位
  float voltage = (rawValue * 5.0) / 1023.0;
  float current = (voltage - 2.5) / currentCalibrationFactor; // 减去零点电压
  
  // 处理负电流值（如果传感器支持双向测量）
  if (abs(current) < 0.02) { // 20mA的死区，用于消除噪声
    current = 0.0;
  }
  
  return current;
}

// 读取原始电压值
float PowerMonitor::readRawVoltage() {
  // 读取电压传感器的原始值
  int rawValue = analogRead(voltageSensorPin);
  
  // 将原始值转换为电压值 (V)
  // 假设Arduino的参考电压为5V，ADC分辨率为10位
  float voltage = (rawValue * 5.0) / 1023.0;
  
  // 根据分压电路计算实际电压
  voltage = voltage / voltageCalibrationFactor;
  
  return voltage;
}

// 计算功率
float PowerMonitor::calculatePower(float voltage, float current) {
  return voltage * current;
}

// 计算电能
void PowerMonitor::calculateEnergy(float power) {
  // 计算从上次计算到现在的时间差（小时）
  unsigned long currentMillis = millis();
  float timeDiffHours = (currentMillis - previousMillis) / 3600000.0; // 转换为小时
  
  // 计算这段时间内消耗的电能（kWh）
  float energyConsumed = (power * timeDiffHours) / 1000.0;
  
  // 更新累积电能
  accumulatedEnergy += energyConsumed;
  
  // 更新时间戳
  previousMillis = currentMillis;
}

// 读取电力数据
PowerData PowerMonitor::readData() {
  PowerData data;
  
  // 获取当前时间戳
  data.timestamp = millis(); // 实际应用中应该使用RTC的时间戳
  
  // 读取电流和电压
  float rawCurrent = readRawCurrent();
  float rawVoltage = readRawVoltage();
  
  // 添加到滤波器缓冲区
  currentSamples[sampleIndex] = rawCurrent;
  voltageSamples[sampleIndex] = rawVoltage;
  sampleIndex = (sampleIndex + 1) % FILTER_SAMPLES;
  
  // 应用低通滤波
  data.current = calculateFilteredValue(currentSamples, FILTER_SAMPLES);
  data.voltage = calculateFilteredValue(voltageSamples, FILTER_SAMPLES);
  
  // 计算功率
  data.power = calculatePower(data.voltage, data.current);
  
  // 计算电能
  calculateEnergy(data.power);
  data.energy = accumulatedEnergy;
  
  return data;
}

// 设置校准参数
void PowerMonitor::setCalibrationFactors(float currentFactor, float voltageFactor) {
  currentCalibrationFactor = currentFactor;
  voltageCalibrationFactor = voltageFactor;
  Serial.print("校准参数已更新 - 电流: ");
  Serial.print(currentCalibrationFactor);
  Serial.print(", 电压: ");
  Serial.println(voltageCalibrationFactor);
}

// 获取累积电能
float PowerMonitor::getAccumulatedEnergy() {
  return accumulatedEnergy;
}

// 重置累积电能
void PowerMonitor::resetAccumulatedEnergy() {
  accumulatedEnergy = 0.0;
  previousMillis = millis();
  Serial.println("累积电能已重置");
}

// 自检功能
bool PowerMonitor::selfTest() {
  // 读取传感器值并检查是否在合理范围内
  float current = readRawCurrent();
  float voltage = readRawVoltage();
  
  bool currentOk = (current >= -0.1 && current <= 0.1); // 没有负载时电流应接近零
  bool voltageOk = (voltage >= 0.0 && voltage <= 300.0); // 电压应在合理范围内
  
  Serial.print("自检结果 - 电流: ");
  Serial.print(current);
  Serial.print(" A, 电压: ");
  Serial.print(voltage);
  Serial.print(" V, 状态: ");
  Serial.println(currentOk && voltageOk ? "通过" : "失败");
  
  return currentOk && voltageOk;
}

// 诊断功能
void PowerMonitor::runDiagnostics() {
  // 读取多次传感器值并计算统计信息
  const int NUM_SAMPLES = 50;
  float currentSum = 0.0;
  float voltageSum = 0.0;
  float currentMin = 1000.0;
  float currentMax = -1000.0;
  float voltageMin = 1000.0;
  float voltageMax = -1000.0;
  
  for (int i = 0; i < NUM_SAMPLES; i++) {
    float current = readRawCurrent();
    float voltage = readRawVoltage();
    
    currentSum += current;
    voltageSum += voltage;
    
    if (current < currentMin) currentMin = current;
    if (current > currentMax) currentMax = current;
    if (voltage < voltageMin) voltageMin = voltage;
    if (voltage > voltageMax) voltageMax = voltage;
    
    delay(20); // 20ms采样间隔
  }
  
  float currentAvg = currentSum / NUM_SAMPLES;
  float voltageAvg = voltageSum / NUM_SAMPLES;
  
  // 计算标准差以评估噪声水平
  float currentVariance = 0.0;
  float voltageVariance = 0.0;
  for (int i = 0; i < NUM_SAMPLES; i++) {
    float current = readRawCurrent();
    float voltage = readRawVoltage();
    
    currentVariance += pow(current - currentAvg, 2);
    voltageVariance += pow(voltage - voltageAvg, 2);
    
    delay(20);
  }
  
  float currentStdDev = sqrt(currentVariance / NUM_SAMPLES);
  float voltageStdDev = sqrt(voltageVariance / NUM_SAMPLES);
  
  // 输出诊断结果
  Serial.println("--- 电力监测器诊断报告 ---");
  Serial.print("电流 - 平均值: ");
  Serial.print(currentAvg, 4);
  Serial.print(" A, 最小值: ");
  Serial.print(currentMin, 4);
  Serial.print(" A, 最大值: ");
  Serial.print(currentMax, 4);
  Serial.print(" A, 标准差: ");
  Serial.print(currentStdDev, 6);
  Serial.println(" A");
  
  Serial.print("电压 - 平均值: ");
  Serial.print(voltageAvg, 4);
  Serial.print(" V, 最小值: ");
  Serial.print(voltageMin, 4);
  Serial.print(" V, 最大值: ");
  Serial.print(voltageMax, 4);
  Serial.print(" V, 标准差: ");
  Serial.print(voltageStdDev, 6);
  Serial.println(" V");
  
  // 评估信号质量
  Serial.print("电流信号质量: ");
  if (currentStdDev < 0.001) {
    Serial.println("优秀");
  } else if (currentStdDev < 0.005) {
    Serial.println("良好");
  } else if (currentStdDev < 0.01) {
    Serial.println("一般");
  } else {
    Serial.println("较差，建议检查连接");
  }
  
  Serial.print("电压信号质量: ");
  if (voltageStdDev < 0.01) {
    Serial.println("优秀");
  } else if (voltageStdDev < 0.05) {
    Serial.println("良好");
  } else if (voltageStdDev < 0.1) {
    Serial.println("一般");
  } else {
    Serial.println("较差，建议检查连接");
  }
  
  Serial.println("---------------------------");
}

#endif // POWER_MONITOR_H